﻿/**
 * ...
 * @author alijaya
 */

package heox;
import heox.events.PositionEvent;
import hevex.EventDispatcher;

class Point extends EventDispatcher
{

	public var initX(default, null):Float;
	public var initY(default, null):Float;
	
	public var length(get_length, null) : Float;
	
	private function get_length() : Float
	{
		return Math.sqrt(x*x + y*y);
	}
	
	/////////////////////////
	// Position Properties //
	/////////////////////////
	
	private var fixedX:Null<Float>;
	private var fixedY:Null<Float>;
	
	
	private var _x : Float;
	public var x(get_x, set_x) : Float;
	
	private function get_x() : Float
	{
		return _x;
	}
	
	private function set_x(value:Float) : Float
	{
		_x = (fixedX == null)?value:fixedX;
		update_x();
		dispatchEvent(new PositionEvent(PositionEvent.X, x, y));
		dispatchEvent(new PositionEvent(PositionEvent.X_OR_Y, x, y));
		return value;
	}
	
	private var _y : Float;
	public var y(get_y, set_y) : Float;
	
	private function get_y() : Float
	{
		return _y;
	}
	
	private function set_y(value:Float) : Float
	{
		_y = (fixedY == null)?value:fixedY;
		update_y();
		dispatchEvent(new PositionEvent(PositionEvent.Y, x, y));
		dispatchEvent(new PositionEvent(PositionEvent.X_OR_Y, x, y));
		return value;
	}
	
	/////////////////
	// Constructor //
	/////////////////
	
	public function new(?x:Float = 0, ?y:Float = 0) 
	{
		super();
		this.initX = 0;
		this.initY = 0;
		this.fixedX = null;
		this.fixedY = null;
		this._x = x;
		this._y = y;
	}
	
	public function clone() : Point
	{
		return new Point(this.x, this.y);
	}
	
	public function toInit()
	{
		setPos(initX, initY);
	}
	
	public function setPos(x:Float, y:Float)
	{
		this.x = x;
		this.y = y;
		dispatchEvent(new PositionEvent(PositionEvent.X_AND_Y, x, y));
	}
	
	
	public static function add(p1:Point, p2:Point) : Point
	{
		var p:Point = p1.clone();
		p.add(p2);
		return p;
	}
	
	public static function subtract(p1:Point, p2:Point) : Point
	{
		var p:Point = p1.clone();
		p.subtract(p2);
		return p;
	}
	
	public static function interpolate(p1:Point, p2:Point, f:Float) : Point
	{
		var p:Point = Point.subtract(p2, p1);
		p.x *= f;
		p.y *= f;
		return p;
	}
	
	public static function polar(length:Float, angle:Float) : Point
	{
		var p:Point = new Point();
		p.x = length * Math.cos(angle);
		p.y = length * Math.sin(angle);
		return p;
	}
	
	public static function distance(p1:Point, p2:Point) : Float
	{
		var p:Point = Point.subtract(p1, p2);
		return p.length;
	}
	
	public static function equals(p1:Point, p2:Point) : Bool
	{
		return (p1.x == p2.x && p1.y == p2.y);
	}
	
	
	public function add(p:Point)
	{
		x += p.x;
		y += p.y;
	}
	
	public function subtract(p:Point)
	{
		x -= p.x;
		y -= p.y;
	}
	
	public function normalize(thickness:Float)
	{
		var c:Float = thickness / length;
		x *= c;
		y *= c;
	}
	
	
	
	#if flash9
	public static function flashPoint(p:Point) : flash.geom.Point
	{
		return new flash.geom.Point(p.x, p.y);
	}
	
	public static function haxePoint(p:flash.geom.Point) : Point
	{
		return new Point(p.x, p.y);
	}
	#end
	
	/////////////////////
	// Update Function //
	/////////////////////
	
	private function update_x()
	{
		
	}
	
	private function update_y()
	{
		
	}
	
	public function toString() : String
	{
		var s:String = "{ x:" + x + ", y:" + y + " }";
		return s;
	}
	
}